/*-
 * Copyright (c) 2009 Jonathan Anderson
 * All rights reserved.
 *
 * WARNING: THIS IS EXPERIMENTAL SECURITY SOFTWARE THAT MUST NOT BE RELIED
 * ON IN PRODUCTION SYSTEMS.  IT WILL BREAK YOUR SOFTWARE IN NEW AND
 * UNEXPECTED WAYS.
 * 
 * This software was developed at the University of Cambridge Computer
 * Laboratory with support from a grant from Google, Inc. 
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#include <QtCore/QString>

#include <QtDBus/QDBusConnection>
#include <QtDBus/QDBusMessage>

#include <iostream>

#include <errno.h>

#include "dbus.h"

using namespace std;


QStringList dbus_powerbox(struct ua_powerbox_options *options)
{
	QString serviceName;

	switch(options->ui)
	{
		case UA_DUMMY:   serviceName = "org.freebsd.capsicum.dummy"; break;
		case UA_QT:      serviceName = "org.freebsd.capsicum.qt";    break;
		case UA_KDE:     serviceName = "org.freebsd.capsicum.kde";   break;
		default:
			cerr << "Unknown UI " << options->ui << "; expected KDE ("
			     << UA_KDE << ") or QT (" << UA_QT << ")" << endl;
		return QStringList();
	}

	QString path = "/PowerboxServer";
	QString interface = "";
	QString methodName = "showPowerbox";
	QString winid = "0x";
	winid += QString::number(options->parent_window, 16);



	QDBusConnection dbus = QDBusConnection::sessionBus();
	if(!dbus.isConnected())
	{
		cerr << "Not connected to session D-Bus" << endl;
		return QStringList();
	}

	QDBusMessage method = QDBusMessage::createMethodCall(
		serviceName, path, interface, methodName);

	QList<QVariant> arguments;
	arguments << options->operation;
	arguments << options->window_title;
	arguments << winid;
	arguments << options->start_path;
	arguments << options->filter;
	arguments << (bool) options->mult;

	method.setArguments(arguments);

	static const int TIMEOUT = 5 * 60 * 1000;  // timeout after 5 mins

	QDBusMessage reply = dbus.call(method, QDBus::Block, TIMEOUT);
	if(reply.type() == QDBusMessage::ErrorMessage)
		if(reply.errorName() == "org.freedesktop.DBus.Error.NoReply")
		{
			errno = ETIMEDOUT;
			return QStringList();
		}
		else
		{
			cerr
				<< "Error opening powerbox - "
				<< reply.errorName().toStdString() << ": "
				<< reply.errorMessage().toStdString() << endl;

			return QStringList();
		}


	QList<QVariant> replyArgs = reply.arguments();
	if(replyArgs.size() != 1)
	{
		cerr << "Received " << replyArgs.size() << " response args, not 1"
		     << endl;

		return QStringList();
	}

	if(replyArgs.at(0).type() != QVariant::StringList)
	{
		cerr << "Received " << replyArgs.at(0).typeName()
		     << " response, not StringList" << endl;

		return QStringList();
	}


	return replyArgs.at(0).toStringList();
}

